package com.dayaokeji.server_api;

import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import me.jessyan.retrofiturlmanager.RetrofitUrlManager;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * retrofit 工具类
 */
public class ApiUtils {

    public static final String LOCAL_BASE_URL = "http://192.168.1.100:8080/";
//    public static final String LOCAL_BASE_URL = "http://192.168.1.81:8080/";
//    public static final String LOCAL_BASE_URL = "http://192.168.1.107:8080/";
//    public static final String LOCAL_BASE_URL = "http://api.dayaokeji.com/";
    public static final String BASE_URL = "http://api.dayaokeji.com/";

    private static final String HEADER_ACCESS_TOKEN = "token";
    private static Retrofit retrofit;
    private static Map<Class,Object> apiCache = new HashMap<>();
    private static boolean init;
    private static Gson gson;

    public static void init(AccessTokenProvider accessTokenProvider,Logger logger,boolean isProdEnv) {
        if (init) throw new IllegalStateException("ApiUtils already initialized");
        retrofit = new Retrofit.Builder()
                .baseUrl(isProdEnv ? BASE_URL : LOCAL_BASE_URL)
                .client(createOkHttpClient(accessTokenProvider,logger))
                .addConverterFactory(GsonConverterFactory.create(createGson()))
                .build();
        init = true;
    }

    public static <T> T getApi(Class<T> apiClass) {

        checkInit();

        synchronized (apiCache) {
            T api = (T) apiCache.get(apiClass);
            if (api == null) {
                api = retrofit.create(apiClass);
                apiCache.put(apiClass,api);
            }
            return api;
        }
    }


    private static void checkInit() {
        if (!init) throw new IllegalStateException("pleas call init() initialized");
    }

    /**
     * create gson handle time
     * @return
     */
    public static Gson createGson() {
        if (gson == null) {
            gson = new GsonBuilder()
                    .registerTypeAdapter(Date.class, new TypeAdapter<Date>() {
                        @Override
                        public void write(JsonWriter out, Date value) throws IOException {
                            out.value(value == null?null:value.getTime());
                        }

                        @Override
                        public Date read(JsonReader in) throws IOException {
                            if (in.peek() == JsonToken.NULL) {
                                in.nextNull();
                                return null;
                            }
                            return new Date(in.nextLong());
                        }
                    })
                    .create();
        }

        return gson;
    }


    /**
     * 创建HttpClient
     * @param accessTokenProvider
     * @param logger
     * @return
     */
    private static OkHttpClient createOkHttpClient(final AccessTokenProvider accessTokenProvider, final Logger logger) {

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if (request.header(HEADER_ACCESS_TOKEN) == null && accessTokenProvider != null) {
                    String token = accessTokenProvider.getToken();
                    if (!TextUtils.isEmpty(token)) {
                        request = request.newBuilder().addHeader(HEADER_ACCESS_TOKEN, token).build();
                    }
                }
                return chain.proceed(request);
            }
        });


        builder.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                long startTime = System.currentTimeMillis();
                logger.log(Logger.Type.RAW,String.format("Sending request %s on %s%n%s",request.url(),chain.connection(),request.headers()));
                Response response = chain.proceed(request);
                long endTime = System.currentTimeMillis();
                logger.log(Logger.Type.RAW,String.format(Locale.CHINA,"Received response for %s in %dms%n%s",response.request().url(),(endTime-startTime),response.headers()));

                byte[] responseBytes = response.body().bytes();
                final String responseStr = new String(responseBytes);
                logger.log(Logger.Type.JSON,responseStr);

                return response.newBuilder().body(ResponseBody.create(MediaType.parse("application/json;charset=UTF-8"),responseBytes)).build();
            }
        });

        return RetrofitUrlManager.getInstance().with(builder).build();

    }

}
